from rest_framework.viewsets import GenericViewSet
from rest_framework.response import Response
from django_filters import FilterSet, filters
from django_filters.rest_framework import DjangoFilterBackend

from api import models
from api.serializers.collect import CollectSerializer
from api.extension.filter import SelfFilterBackend
from api.extension.mixins import DigCreateModelMixin, DigListModelMixin
from api.extension import return_code


class CollectFilterSet(FilterSet):
    # 定义一个latest_id，用于分页查询（下拉加载更多）
    # 原理举例：
    #   1、这次获取了10条数据，然后获取这10条的最后一条的id
    #   2、根据这个id，加载更多查询的时候，就查询小于/大于（根据数据的排序规则来决定）这条数据的，相当于多给了个查询条件
    # 优点：这样做就避免了，当有新增/删除数据时，原来的分页查询方式造成数据重复（查出来有重复的数据）
    # 传统的，如果按照每页多少条的方式，当前页的数据被删除或有新增时，点击下一页，就会出现新加载的数据包含当前页的数据，出现重复
    latest_id = filters.NumberFilter(field_name='id', lookup_expr='lt')

    class Meta:
        model = models.Collect
        fields = ["latest_id", ]


class CollectView(DigCreateModelMixin, DigListModelMixin, GenericViewSet):
    """ 收藏接口 """
    # SelfFilterBackend：只能看到自己的收藏
    filter_backends = [SelfFilterBackend, DjangoFilterBackend]
    filterset_class = CollectFilterSet

    # 当前登录用户的所有收藏记录
    queryset = models.Collect.objects
    serializer_class = CollectSerializer

    def perform_create(self, serializer):
        # 由于这里的“收藏”-------通过 点击 来 进行收藏/取消收藏
        #   点击了，那么图标就标红，成功收藏
        #   再点击一下就取消收藏
        # 前端通过点击元素来调用接口，因此这里的 创建/取消 都得放在 同一个接口的同一个请求方法 里
        # 再根据active来判断该元素图标是否标红
        user = self.request.user
        # 查询用户 是否收藏了 这条资讯（用户和资讯 构成 联合唯一索引）
        instance = models.Collect.objects.filter(user=user, **serializer.validated_data).first()
        if not instance:
            instance = serializer.save(user=user)
            instance.news.collect_count += 1
            instance.news.save()
            return Response({"code": return_code.SUCCESS, 'data': {'active': True}})
        else:
            # 在收藏表中删除该记录
            instance.delete()
            # 修改该资讯的收藏数
            instance.news.collect_count -= 1
            instance.news.save()
            return Response({"code": return_code.SUCCESS, 'data': {'active': False}})
